<template>
  <div>
    <div class="selectr">
      选择教室
      <el-cascader
        ref="clroom"
        v-model="classroom"
        placeholder="选择教室"
        :options="roomOption"
        :props="SetKesDept"
        @change="elect"
      ></el-cascader>
      &nbsp; &nbsp; {{ $store.state.pxswitch ? "培训" : "考试" }}场次
      <el-select
        ref="mark"
        v-model="infoval"
        style="width: 160px"
        placeholder="请选择"
        clearable
        @change="testChange($event)"
      >
        <el-option
          v-for="item in testInfor"
          :key="item.examinationId"
          :label="item.examinationName"
          :value="item.examinationId"
        >
        </el-option>
      </el-select>
      &nbsp; &nbsp; &nbsp; &nbsp;
      <el-button type="primary" :disabled="isdisable" @click="startExa">
        开始{{ $store.state.pxswitch ? "培训" : "考试" }}
      </el-button>
      &nbsp; &nbsp;
      <el-button type="primary" :disabled="isdisable2" @click="stopexam">
        结束{{ $store.state.pxswitch ? "培训" : "考试" }}
      </el-button>
    </div>
    <div class="content">
      <!-- <div class="tree">
        <h3>设备列表</h3>
        <el-tree
          :data="options"
          :props="SetKesDept"
          accordion
          @node-click="handleNodeClick"
        >
        </el-tree>
      </div> -->
      <ul class="dirllList">
        <h3>考试全流程跟踪</h3>
        <li v-for="(item, i) in steps" :key="i" @click="lookImage($event)">
          <div
            class="jklist"
            :studentid="item.studentId"
            :equipmentId="item.equipmentId"
            :statusStudent="item.faceVerification"
            :studentName="item.studentName"
          >
            <div class="namej">
              <svg
                v-if="
                  item.faceVerification != 0 &&
                  item.faceVerification != undefined &&
                  item.examStatus != 2
                "
                xmlns="http://www.w3.org/2000/svg"
                t="1625622952499"
                class="icon"
                viewBox="0 0 1024 1024"
                version="1.1"
                p-id="1955"
                width="18"
                height="18"
              >
                <path
                  d="M511.573 0.853C233.067 0.853 6.55 223.445 0.15 500.416 6.06 258.731 189.824 64.811 415.66 64.811c229.546 0 415.658 200.426 415.658 447.616 0 52.97 42.944 95.936 95.915 95.936 52.95 0 95.915-42.966 95.915-95.936C1023.147 229.888 794.112 0.853 511.573 0.853z m0 1023.147c278.507 0 505.024-222.592 511.403-499.563-5.888 241.664-189.653 435.627-415.488 435.627-229.547 0-415.659-200.448-415.659-447.637 0-52.95-42.965-95.915-95.936-95.915C42.965 416.512 0 459.456 0 512.427 0 794.965 229.035 1024 511.573 1024z"
                  fill="#08af26"
                  p-id="1956"
                />
              </svg>
              <i v-else class="yuan"></i>

              <span :title="item.equipmentName"> {{ item.equipmentName }}</span>
            </div>
            <dd class="el-step__arrow" stats="0">
              <div
                class="ditem"
                :class="
                  item.faceVerification == 1 ? 'itemsuccess' : 'itemerror'
                "
              >
                <!-- <img
                  src="@/assets/moren.png"
                  alt=""
                > -->
                <img
                  v-if="item.faceVerification == 1"
                  :src="
                    item.images == undefined
                      ? ``
                      : `http://117.160.141.22:6085/platform/management/faceImage/${item.images}.jpg`
                  "
                  alt=""
                />
              </div>
              <span>{{
                item.studentName == null ? "考生姓名" : item.studentName
              }}</span>
            </dd>
            <dd class="el-step__arrow" stats="3">
              <div
                class="ditem"
                :class="
                  item.helmetDetection == 0
                    ? 'itemsuccess'
                    : item.helmetDetection == null
                    ? ''
                    : 'itemerror'
                "
              >
                {{ item.helmetDetection }}
              </div>
              <span>安全帽检测</span>
            </dd>
            <dd class="el-step__arrow">
              <div
                class="ditem"
                :class="
                  item.toolingDetection == 0
                    ? 'itemsuccess'
                    : item.toolingDetection == null
                    ? ''
                    : 'itemerror'
                "
              >
                {{ item.toolingDetection }}
              </div>
              <span>工装检测</span>
            </dd>

            <dd class="el-step__arrow" stats="2">
              <div
                class="ditem"
                :class="
                  item.peopleDetection == 0
                    ? 'itemsuccess'
                    : item.peopleDetection == null
                    ? ''
                    : 'itemerror'
                "
              >
                {{ item.peopleDetection }}
              </div>
              <span>人员聚集</span>
            </dd>

            <dd class="el-step__arrow" stats="1">
              <div
                class="ditem"
                :class="
                  item.outDetection == 0
                    ? 'itemsuccess'
                    : item.outDetection == null
                    ? ''
                    : 'itemerror'
                "
              >
                {{ item.outDetection }}
              </div>
              <span>越界检测</span>
            </dd>
            <dd class="el-step__arrow">
              <div
                class="ditem"
                :class="item.examStatus != 2 ? '' : 'itemsuccess'"
              >
                <!-- <i
                  v-show="item.examStatus == 2"
                  class="el-icon-check"
                  style="
                    color: #03a613;
                    font-size: 42px;
                    font-weight: bold;
                    line-height: 70px;
                  "
                ></i> -->
                {{
                  item.examStatus == 2
                    ? 100 -
                      item.helmetDetection -
                      item.toolingDetection -
                      item.peopleDetection -
                      item.outDetection
                    : ""
                }}
                <sub v-show="item.examStatus == 2">分</sub>
              </div>
              <span>
                {{
                  item.examStatus == 2
                    ? "完成"
                    : item.faceVerification != 0 &&
                      item.faceVerification != undefined &&
                      item.examStatus != 2
                    ? "进行中"
                    : "未开始"
                }}
              </span>
            </dd>
          </div>
          <button
            class="el-icon-monitor viewPrade"
            @click="
              () => {
                infoval
                  ? $router.push({ name: 'Grade', params: { id: infoval } })
                  : '';
              }
            "
          >
            查看评分
          </button>
        </li>
      </ul>
    </div>
    <el-dialog
      v-dialogDrag
      title="提示"
      :visible.sync="timeVisible"
      width="30%"
    >
      <!-- :before-close="handleClose" -->
      <span>已过考试结束时间!请重新选择!</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="timeEvent">取 消</el-button>
        <el-button type="primary" @click="timeEvent">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 图片展示 -->
    <el-dialog
      v-dialogDrag
      title="抓拍图片(点击图片查看大图)"
      :visible.sync="centerDialogVisible"
      width="80%"
      center
    >
      <ul class="imglist">
        <el-popover
          v-for="item in imgdata"
          :key="item"
          placement="bottom"
          trigger="click"
        >
          <img :src="imgsrc" alt="" style="width: 620px; height: auto" />
          <li slot="reference" @click="popover($event)">
            <img
              :src="`http://117.160.141.22:6085/platform/management/detection/${item}`"
              alt=""
              @error="imgExists($event)"
            />
          </li>
        </el-popover>
      </ul>
      <span slot="footer" class="dialog-footer">
        <el-button @click="centerDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="centerDialogVisible = false"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>
<script>
const synth = window.speechSynthesis;
const msg = new SpeechSynthesisUtterance();
// 上面是音频
import {
  ksks,
  stopExam,
  querytreeFloor,
  quSelecteq,
  queryeroom,
  kstatus,
  queryImage,
  startExamTest,
} from "@/api";
// import STeps from "@/components/steps";
export default {
  name: "Monitor",
  data() {
    return {
      active: 1,
      classroom: "",
      SetKesDept: {
        value: "id",
        label: "title",
      }, //自定义  级联选择器value label
      roomOption: [],
      sopt: [],
      infoval: "", // websockit链接id
      testInfor: [], //根据教室获得考试信息
      isdisable: false,
      isdisable2: false,
      centerDialogVisible: false,
      imgdata: [],
      istype: "",
      stopInterval: null,
      steps: [], //考试机器列表
      // steps2: [], // 备用
      // stuid:10049,
      imgsrc: "",
      studentId: "", //学生id
      socket: null,
      reconnectData: null,
      lockReconnect: false, //避免重复连接，因为onerror之后会立即触发 onclose
      timeout: 10000, //10s一次心跳检测
      timeoutObj: null,
      serverTimeoutObj: null,
      timeVisible: false,
      timeEnd: "", //考试结束时间this.infoval
      nowTime: "", // 获取网络时间
      usedTime: "", // 考试用时
      examStatusFn() {
        kstatus({
          examinationId: this.infoval,
        })
          .then((res) => {
            console.log(res);
            this.nowTime = new Date(res.headers.date).getTime();
            let data = res.data.data;
            this.isdisable = false;

            let ss = this.testInfor.filter((item) => {
              return item.examinationId == this.infoval;
            });
            this.steps = this.steps.map((item) => {
              data.forEach((iit) => {
                if (item.equipmentId == iit.equipmentId) {
                  item = iit;
                }
              });
              return item;
            });
            if (ss[0].examStatus == 1) {
              this.isdisable = true;
              this.init();
            }
            if (this.nowTime > this.timeEnd) {
              this.isdisable = true;
            }
            // this.isdisable2 = false;
          })
          .catch((err) => {
            console.log(err);
          });
      },
    };
  },
  destroyed() {
    // 销毁websocket
    // this.socket.close();
    this.lockReconnect = true;
    clearTimeout(this.reconnectData); //离开清除 timeout
    clearTimeout(this.timeoutObj); //离开清除 timeout
    clearTimeout(this.serverTimeoutObj); //离开清除 timeout
  },
  activated() {
    if (this.classroom) {
      queryeroom({
        roomId: this.classroom[1],
        usersId: localStorage.getItem("usersId"),
      }).then((res) => {
        this.testInfor = res.data;
      });
      if (this.infoval) {
        this.testChange(this.infoval);
      }
    }
  },
  deactivated() {
    console.log("页面失效");
  },
  mounted() {
    this.querFloor();
  },
  // components: { STeps },
  methods: {
    handleSpeak(text) {
      msg.text = text; // 文字内容:
      msg.lang = "zh-CN"; // 使用的语言:中文
      msg.volume = 2; // 声音音量：1
      msg.rate = 1; // 语速：1
      msg.pitch = 2; // 音高：1
      synth.speak(msg); // 播放
    },
    querFloor() {
      querytreeFloor()
        .then((res) => {
          console.log(res);
          this.roomOption = res.data;
        })
        .then((dates) => {
          console.log(dates);
        })
        .catch((err) => {
          console.log(err);
        });
    },
    elect(value) {
      if (value.length > 0) {
        quSelecteq({
          roomCode: value[1],
          usersId: localStorage.getItem("usersId"),
        }).then((res) => {
          this.steps = [];
          let aa = [];
          res.data.forEach((item) => {
            this.steps.push(item);
            aa.push(item);
            // this.steps2 = aa;
          });
        });
        // .catch((err) => {
        //   console.log(err);
        // });
        queryeroom({
          roomId: value[1],
          usersId: localStorage.getItem("usersId"),
        }).then((res) => {
          this.testInfor = res.data;
        });
        if (this.infoval != "") {
          this.infoval = "";
        }
      }
    },
    lookImage(ev) {
      let nums = ev.path[1].getAttribute("stats");
      console.log(nums);
      let imageType = nums;
      let studentId = ev.path[2].getAttribute("studentid"); // 学生id
      let equipmentId = ev.path[2].getAttribute("equipmentId"); // 机器id
      let statusStudent = ev.path[2].getAttribute("statusStudent"); // 人脸验证是否通过
      let studentName = ev.path[2].getAttribute("studentName"); // 考试姓名
      console.log();
      if (this.infoval !== "" && studentId) {
        if (nums != 0 && nums !== null && statusStudent != 0) {
          // 越界检测
          queryImage({ examinationId: this.infoval, studentId, imageType }) //this.studentId 考试学生的id
            .then((res) => {
              console.log(res);
              if (res.result_code == 200) {
                if (res.data.length > 0) {
                  this.imgdata = res.data;
                  this.centerDialogVisible = true;
                } else {
                  this.$message.warning("未找到违规图片!");
                }
              }
            })
            .catch((err) => {
              console.log(err);
            });
        }
        if (nums == 0 && studentId) {
          if (this.isdisable && statusStudent != 1) {
            this.$confirm(
              `此操作将开始考生：${studentName} 的考试, 是否继续?`,
              "提示",
              {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
              }
            )
              .then(() => {
                startExamTest({
                  // 手动k开始某个考试
                  examId: this.infoval,
                  studentId,
                  equipmentId,
                })
                  .then((res) => {
                    if (res.result_code == 200) {
                      this.$message.success("开始考试!");
                    }
                  })
                  .catch((err) => {
                    console.log(err);
                  });
              })
              .catch(() => {
                this.$message({
                  type: "info",
                  message: "已取消",
                });
              });
          }
        }
        // console.log(nums);
      }
    },

    //点击查看大图
    popover(e) {
      this.imgsrc = e.target.currentSrc;
    },

    // init websockte
    init: function (rid = this.infoval) {
      if (typeof WebSocket === "undefined") {
        alert("您的浏览器不支持webSocket");
      } else {
        // 实例化socket
        this.socket = new WebSocket(
          "ws://117.158.147.214:6085/platform/identify/api/websocket/" + rid
        );
        // 监听socket连接
        this.socket.onopen = this.open;
        // 监听socket错误信息
        this.socket.onerror = this.error;
        // 监听socket消息
        this.socket.onmessage = this.getMessage;
        this.socket.onclose = this.websocketclose;
      }
    },
    open: function () {
      console.log("socket连接成功");
    },
    error: function () {
      console.log("连接错误");
      this.reconnect();
    },
    getMessage: function (msg) {
      let data = JSON.parse(msg.data);
      // console.log(data);
      this.steps = this.steps.map((item) => {
        if (item.equipmentId == data.equipmentId) {
          item = data;
        }
        return item;
      });
    },
    websocketclose() {
      console.log("断开连接");
      this.reconnect();
    },
    send: function (data) {
      this.socket.send(JSON.stringify(data));
    },
    reconnect() {
      if (this.lockReconnect) {
        //这里很关键，因为连接失败之后之后会相继触发 连接关闭，不然会连接上两个 WebSocket
        return;
      }
      this.lockReconnect = true;
      this.reconnectData && clearTimeout(this.reconnectData);
      this.reconnectData = setTimeout(() => {
        this.init();
        this.lockReconnect = false;
      }, 5000);
    }, //socket重连

    // 获取考试流程状态
    testChange(val) {
      if (val) {
        this.examStatusFn();
        // 获取考试结束时间
        var dtimes = this.testInfor.filter((item) => {
          return item.examinationId == val;
        });
        this.timeEnd = new Date(dtimes[0].endTime).getTime();
        this.usedTime =
          (this.timeEnd - new Date(dtimes[0].startTime).getTime()) / 1000 / 60;
        this.sjs();
      }
    },
    startExa() {
      if (this.classroom == "" || this.infoval == "") {
        this.$message({
          message: `请选择一个${
            this.$store.state.pxswitch ? "培训" : "考试"
          }场次`,
          type: "warning",
        });
        if (this.classroom == "") {
          this.$refs.clroom.$el.click();
        } else {
          this.$refs.mark.$el.click();
        }
      } else {
        this.$confirm("此操作将开始本场考试, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(() => {
            ksks({
              examinationId: this.infoval,
              roomId: this.classroom[1],
            })
              .then((res) => {
                console.log(res);
                if (res.result_code == 500) {
                  this.$confirm(res.data, "提示", {
                    confirmButtonText: "确定",
                    cancelButtonText: "取消",
                    type: "warning",
                  });
                } else {
                  this.isdisable = true;
                  this.$store.commit("setExaminId", this.infoval);
                  this.$store.state.pxswitch
                    ? (() => {
                        this.$message.success("开始培训!");
                        this.handleSpeak("培训也开始,请按要求完成本次培训！");
                      })()
                    : (() => {
                        this.$message.success("开始考试！");
                        this.handleSpeak(
                          "考试已开始，请考生到指定位置进行考试"
                        );
                      })();

                  this.isdisable2 = false;
                  this.init();
                }
              })
              .catch((err) => {
                console.log(err);
              });
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消",
            });
          });
      }
    },
    stopexam() {
      if (this.infoval == "" || this.classroom == "") {
        this.$message({
          message: `请选择一个${
            this.$store.state.pxswitch ? "培训" : "考试"
          }场次`,
          type: "warning",
        });

        if (this.classroom == "") {
          this.$refs.clroom.$el.click();
        } else {
          this.$refs.mark.$el.click();
        }
      } else {
        if (this.isdisable) {
          this.$confirm("此操作将结束本场考试, 是否继续?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          })
            .then(() => {
              stopExam({
                examinationId: this.infoval,
              })
                .then((res) => {
                  if (res.result_code == 200) {
                    this.isdisable2 = true;
                    this.$message({
                      type: "success",
                      message: "本场考试结束!",
                    });
                    clearInterval(this.stopInterval);
                    this.examStatusFn();
                    this.testInfor = [];
                    this.$store.state.pxswitch
                      ? this.handleSpeak("本次培训已结束，请考生按顺序离场")
                      : this.handleSpeak("考试已结束，请考生按顺序离场"),
                      this.$store.commit("setUsedTime", this.usedTime);
                  }
                })
                .catch((err) => {
                  console.log(err);
                });
            })
            .catch(() => {
              this.$message({
                type: "info",
                message: "已取消",
              });
            });
        } else {
          this.$message.warning("本场考试未开始");
        }
      }
    },
    // 返回考试结束信息

    //结束考试判断
    sjs() {
      if (this.nowTime > this.timeEnd) {
        this.examStatusFn();
        this.testInfor = [];
        this.classroom = "";
        this.isdisable = false;
        this.isdisable2 = false;
        this.timeVisible = true;
        this.$store.state.pxswitch
          ? this.handleSpeak("本次培训已结束，请考生按顺序离场")
          : this.handleSpeak("考试已结束，请考生按顺序离场"),
          this.$store.commit("setUsedTime", this.usedTime);
      } else {
        this.stopInterval = setTimeout(() => {
          this.nowTime = this.nowTime + 3000;
          this.sjs();
        }, 3000);
      }
    },
    timeEvent() {
      this.classroom = "";
      this.isdisable = false;
      this.isdisable2 = false;
      this.timeVisible = false;
    },
  },
};
</script>
<style lang="scss" scoped>
.selectr {
  text-align: left;
  font-size: 16px;
  text-indent: 5px;
  padding-bottom: 10px;
  // border-bottom: 1px solid #bbb;
  box-shadow: 0px 5px 5px -5px #666;
  margin-bottom: 20px;
}
.content {
  display: flex;
  height: 100%;

  .tree {
    flex: 1;
    margin-right: 15px;
    background: #f2f2f2;
    h3 {
      background: #18a5a5;
      padding: 10px;
    }
    .el-tree {
      padding: 10px;
      height: 100%;
      background: none;
      color: #666;
    }
  }
}
.dirllList {
  display: flex;
  flex: 3;
  flex-flow: column;
  h3 {
    font-size: 18px;
    line-height: 26px;
    padding: 10px;
    background: #18a5a5;
    color: white;
  }
  li {
    border-bottom: 1px solid #18a5a5;
    background: #f2f2f2;
    padding: 10px;
    display: flex;
    flex-direction: revert;
    color: #555;

    .jklist {
      display: flex;
      flex: 5;
    }

    sub {
      font-size: 14px;
      font-weight: normal;
      margin-left: -3px;
    }
    .viewPrade {
      width: auto;
      height: 35px;
      margin-top: 25px;
      border: none;
      background: #18a5a5;
      color: white;
      border-radius: 5px;
    }
  }
  li:last-child {
    margin: 0;
    border: none;
  }
}
.namej {
  float: left;
  width: 10%;
  min-width: 117px;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  span {
    vertical-align: super;
    font-size: 14px;
    cursor: pointer;
  }
}
.namej svg {
  width: 25px;
  height: 25px;
  margin: 35px 10px 0 5px;
  animation: loading 1.5s linear infinite;
}
@keyframes loading {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}
dd {
  width: 14.28%;
  float: left;
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  flex: 1 auto;
  height: auto;

  span {
    display: block;
    float: left;
  }

  .ditem {
    cursor: pointer;
    box-sizing: border-box;
    border: 2px #aaa solid;
    width: 70px;
    height: 70px;
    text-align: center;
    line-height: 70px;
    font-size: 26px;
    font-weight: 600;
    margin-bottom: 5px;
    background: #fff;
    img {
      width: 100%;
      height: 100%;
    }
  }
  .itemsuccess {
    border-image: linear-gradient(130deg, #03a613, #03d718) 10 10;
  }
  .itemerror {
    border: 2px dashed #ad0a0a;
    // border-image:linear-gradient(130deg, #ad0a0a, #e21616) 1 1;
  }

  span {
    font-size: 14px;
  }
}
.el-steps--simple {
  padding: 0 10px;
  position: relative;
}
.el-step__arrow:last-child::after,
.el-step__arrow:last-child::before {
  width: 0;
}
.el-step__arrow::after,
.el-step__arrow::before {
  content: "";
  display: inline-block;
  position: absolute;
  height: 19px;
  width: 2px;
  right: 0;
  top: 30px;
  background: #395ea3;
}
.el-step__arrow::before {
  transform: rotate(-49deg) translateY(-4px);
  transform-origin: 0 0;
}
.el-step__arrow::after {
  transform: rotate(45deg) translateY(4px);
  transform-origin: 100% 100%;
}
</style>
<style>
.el-message {
  margin-top: 15%;
  padding: 10px 15px;
}
.el-message--warning p {
  font-size: 20px;
}
.imglist {
  width: 100%;
  overflow: hidden;
}
.imglist li {
  float: left;
  overflow: hidden;
}
.imglist li img {
  width: 100px;
  height: 100px;
  margin-right: 5px;
}
</style>
